package serie08;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import serie06.util.DrinkTypes;
import serie06.util.CoinTypes;

public class DrinksMachine {

	// ATTRIBUTS
	
	// La fenetre principale de l'application
	private JFrame frame;
	
	// Le modele
	private StdDrinksMachineModel model;
	
	// Les labels du NORD
	private JLabel label1;
	private JLabel label2;
	
	// L'association bouton-boisson
	private Map<JButton, DrinkTypes> boissons;
	
	// Les 3 boutons
	private JButton inserer;
	private JButton annuler;
	private JButton prenez;
	
	// Les 3 JTextField
	private JTextField montant;
	private JTextField boisson;
	private JTextField monnaie;
	
	// CONSTRUCTEURS
	
	public DrinksMachine() {
		createModel();
        createView();
        placeComponents();
        createController();
		model.notifyObservers();
	}
	
	// COMMANDES

    /**
     * Rend l'application visible au centre de l'�cran.
     */
    public void display() {
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    // OUTILS
    
    private void createModel() {
        model = new StdDrinksMachineModel(); 
        model.fillCashbox();
        model.fillStock();
    }
    
    private void createView() {
    	frame = new JFrame("Distributeur de boissons");
    	boissons = new HashMap<JButton, DrinkTypes>();
    	for (DrinkTypes d : DrinkTypes.values()) {
    		boissons.put(new JButton(d.toString()), d);
    	}
    	inserer = new JButton("Ins�rer");
    	annuler = new JButton("Annuler");
    	prenez = new JButton("Prenez votre boisson et/ou votre monnaie");
    	montant = new JTextField(5);
    	boisson = new JTextField(10);
    	monnaie = new JTextField(7);
    	if (!model.canGetChange()) {
    		label1 = new JLabel("Cet appareil ne rend pas la monnaie");
    	} else {
    		label1 = new JLabel("Cet appareil rend la monnaie");
    	}
    	label2 = new JLabel("Vous disposez d'un credit de 0 cents");
    	model.addObserver(new Observer() {
            public void update(Observable o, Object arg) {
            	for (JButton b : boissons.keySet()) {
            		if (model.getDrinkStock().getNumber(boissons.get(b)) > 0) {
            			b.setEnabled(true);
                	} else {
                		b.setEnabled(false);
                	}
            	}
            	if (!model.canGetChange()) {
            		label1.setText("Cet appareil ne rend pas la monnaie");
            	} else {
            		label1.setText("Cet appareil rend la monnaie");
            	}
            	label2.setText("Vous disposez d'un credit de " 
            					+ model.getCredit().getAmount() + " cents");
            	if (arg != null) {
            		boisson.setText(((DrinkTypes) arg).toString());
            		monnaie.setText(String.valueOf(
            				(model.getChangebox().getAmount())
            		));
            	}
            	if (model.getCredit().getAmount() == 0) {
            		monnaie.setText(String.valueOf(
            				model.getChangebox().getAmount()
            		));
            	}
            }
    	});
    }
    
    private void placeComponents() { 
    	frame.setLayout(new FlowLayout());
    	JPanel t = new JPanel(new BorderLayout()); {
    		// Zone NORD
    		JPanel p = new JPanel(new BorderLayout()); {
    			JPanel q = new JPanel(); {
    				q.add(label1);
    			}
    			p.add(q, BorderLayout.NORTH);
    			q = new JPanel(); {
    				q.add(label2);
    			}
    			p.add(q, BorderLayout.SOUTH);
    		}
    		t.add(p, BorderLayout.NORTH);
    		
    		// Zone OUEST
    		p = new JPanel(new GridLayout(boissons.size(), 2)); {
    			for (JButton b : boissons.keySet()) {
    				p.add(b);
    				p.add(new JLabel(boissons.get(b).getPrice() + " cents"));
    			}
    		}
    		t.add(p, BorderLayout.WEST);
    		
    		// Zone EST
    		p = new JPanel(); {
    			JPanel pp = new JPanel(new GridLayout(2, 2)); {
    				pp.add(inserer);
    				JPanel q = new JPanel(); {
    					q.add(montant);
    					q.add(new JLabel("cents"));
    				}
    				pp.add(q);
    				pp.add(annuler);
    			}
    			p.add(pp);
    		}
    		t.add(p, BorderLayout.EAST);
        
    		// Zone SUD
    		p = new JPanel(new BorderLayout()); {
    			JPanel q = new JPanel(); {
    				q.add(new JLabel("Boisson : "));
    				q.add(boisson);
    			}
    			p.add(q, BorderLayout.WEST);
    			q = new JPanel(); {
    				q.add(new JLabel("Monnaie :"));
    				q.add(monnaie);
    				q.add(new JLabel("cents"));
    			}
    			p.add(q, BorderLayout.EAST);
    			q = new JPanel(); {
    				q.add(prenez);
    			}
    			p.add(q, BorderLayout.SOUTH);
    		}
    		t.add(p, BorderLayout.SOUTH);
    	}
    	frame.add(t);
    }
    
    private void createController() {
    	ActionListener al = new ActionListener() {
    		public void actionPerformed(ActionEvent e) {
    			JButton b = (JButton) e.getSource();
    			int price = boissons.get(b).getPrice();
    			if (model.getCredit().getAmount() >= price) {
    				model.deliverDrink(boissons.get(b));
    			}
    		}
    	};
    	for (JButton b : boissons.keySet()) {
    		b.addActionListener(al);
    	}
    	
    	inserer.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent e) {
    			CoinTypes c = null;
    			try {
    				c = CoinTypes.getCoinTypes(
    						Integer.valueOf(montant.getText())
    					); 
    				model.insertCoin(c);
    			} catch (NumberFormatException f) {
    				montant.setText("");
    			}
    			montant.setText("");
    		}
    	});
    	
    	annuler.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent e) {
    			model.resetCredit();
    			montant.setText("");
    		}
    	});
    	
    	prenez.addActionListener(new ActionListener() {
    		public void actionPerformed(ActionEvent e) {
    			boisson.setText("");
    			monnaie.setText("");
    		}
    	});
    	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new DrinksMachine().display();
            }
        });
    }
}
